package com.testing.sunnycommon.initializer;

import com.testing.sunnycommon.automation.ApiKeywords;
import com.testing.sunnycommon.automation.WebKeywords;
import com.testing.sunnycommon.automation.annotations.KeyDescription;
import com.testing.sunnycommon.automation.annotations.KeyParams;
import com.testing.sunnycommon.automation.annotations.KeyUsage;
import com.testing.sunnycommon.model.SunnyKeywords;
import com.testing.sunnycommon.service.SunnyKeywordsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @Classname KeywordsInitializer
 * @Description 类型说明
 * @Date 2023/5/19 22:00
 * @Created by 特斯汀Roy
 */
@Component
@Slf4j
public class KeywordsInitializer implements ApplicationRunner {
    @Autowired
    SunnyKeywordsService sunnyKeywordsService;


    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("在这里开始keywords信息的自动获取和数据库初始化");
        //删除keywords表中的所有数据
        sunnyKeywordsService.remove(null);
        //遍历keywords中的方法，拼接成keywords对象的列表
        List<SunnyKeywords> sunnyKeywordsList = new ArrayList<>();
        List<SunnyKeywords> apiKeywords = generateKeywordsData(ApiKeywords.class.getName(), "api");
        List<SunnyKeywords> webKeywords = generateKeywordsData(WebKeywords.class.getName(), "web");
        //通过addAll将得到的web和api中的关键字信息拼接到一个list里面，最终插入到数据库
        sunnyKeywordsList.addAll(webKeywords);
        sunnyKeywordsList.addAll(apiKeywords);
        //将keywords对象列表全部新增到数据库里面
        sunnyKeywordsService.saveBatch(sunnyKeywordsList);
    }

    /**
     * 将制定的keywords类型中的方法的注解解析并且拼接成keywords实体对象，得到一个列表
     *
     * @param className keywords类型名
     * @param type      keywords类型  web 或者 api
     * @return 返回解析关键字类中的方法之后得到的keywords信息。
     */
    private List<SunnyKeywords> generateKeywordsData(String className, String type) {

        List<SunnyKeywords> keywordsList = new ArrayList<>();
        try {
            Class clazz = Class.forName(className);
            //获取类中自己定义的方法
            for (Method declaredMethod : clazz.getDeclaredMethods()) {
                //内部方法如果没有任何注解，直接进入下个循环
                if (declaredMethod.getDeclaredAnnotations().length == 0) continue;
                SunnyKeywords keywords = new SunnyKeywords();
                //每个方法的方法名是keywords对象的keywords属性
                keywords.setKeywords(declaredMethod.getName());
                keywords.setName(declaredMethod.getName());
                //id用0，自动递增
                keywords.setId(0L);
                //type类型根据关键字类型来决定
                keywords.setType(type);
                String keyDesc = "";
                for (Annotation declaredAnnotation : declaredMethod.getDeclaredAnnotations()) {
                    //获取keyUsage类型的注解
                    if (declaredAnnotation.annotationType() == KeyUsage.class) {
                        //强转注解为指定类型，再调用获取其中的值
                        keywords.setKeyUsage(((KeyUsage) declaredAnnotation).value());
                    } else if (declaredAnnotation instanceof KeyDescription) {
                        //先拼接keyDesc注解中的内容到描述信息里
                        keyDesc = ((KeyDescription) declaredAnnotation).value();
                    }
                }

                //获取方法中的所有参数的注解
                Annotation[][] parameterAnnotations = declaredMethod.getParameterAnnotations();
                for (Annotation[] parameterAnnotation : parameterAnnotations) {
                    //针对每个参数的所有注解，获取对应的值。
                    for (Annotation annotation : parameterAnnotation) {
                        if (annotation instanceof KeyParams) {
                            keyDesc += "\\n @Param：" + ((KeyParams) annotation).name() + "，参数作用：" + ((KeyParams) annotation).value();
                        }
                    }
                }
                //拼接完成描述信息之后，设置keywords的描述字段
                keywords.setDescription(keyDesc);
                keywordsList.add(keywords);
            }
            return keywordsList;
        } catch (ClassNotFoundException e) {
            log.error("关键字列表获取出错", e.fillInStackTrace());
            return new ArrayList<>();
        }

    }
}
